﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Scripting;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;

namespace DlrBasic.Parser.Ast
{
    class Next : Statement
    {
        VariableOrCall[] variables;

        public Next(SourceSpan span, VariableOrCall[] variables)
            : base(span)
        {
            this.variables = variables;
        }

        protected internal override Expression Generate(DlrBasicGenerator generator, StateMemberGenerator stateParameter, LambdaBuilder builder)
        {
            if (variables == null)
            {
                Expression test = Expression.Call(stateParameter.GetForStackVariable(),
                    typeof(Runtime.DlrBasicForStack).GetMethod("NextAny"));

                Expression @continue = Expression.Call(stateParameter.GetForStackVariable(),
                    typeof(Runtime.DlrBasicForStack).GetMethod("GetContinueState"));

                return Utils.IfThenElse(test,
                    Expression.Assign(stateParameter.GetCurrentStatementVariable(), @continue),
                    base.Generate(generator, stateParameter, builder));
            }
            else
            {
                Expression lastStatement = base.Generate(generator, stateParameter, builder);
                for (int i = variables.Length - 1; i >= 0; i--)
                {
                    Expression test = Expression.Call(stateParameter.GetForStackVariable(),
                        typeof(Runtime.DlrBasicForStack).GetMethod("Next"),
                        Expression.Constant(GetForId(variables[i])));

                    Expression @continue = Expression.Call(stateParameter.GetForStackVariable(),
                        typeof(Runtime.DlrBasicForStack).GetMethod("GetContinueState"));

                    lastStatement = Utils.IfThenElse(test,
                        Expression.Assign(stateParameter.GetCurrentStatementVariable(), @continue),
                        lastStatement);
                }
                return lastStatement;
            }
        }

        private string GetForId(VariableOrCall variableOrCall)
        {
            return variableOrCall.GetFullVariableName();
        }

        public bool HasForIds()
        {
            return variables != null && variables.Length > 0;
        }

        public string[] GetForIds()
        {
            if (HasForIds())
            {
                string[] ids = new string[variables.Length];
                for (int i = 0; i < ids.Length; i++)
                {
                    ids[i] = GetForId(variables[i]);
                }
                return ids;
            }
            return null;
        }
    }
}
